package com.d3works.apps.sale.service.configurator;

import com.d3works.apps.sale.db.Configurator;
import com.d3works.apps.sale.db.SaleOrder;
import com.d3works.db.Model;
import com.d3works.exception.D3worksException;
import com.d3works.meta.db.MetaJsonField;
import com.d3works.rpc.JsonContext;
import java.lang.reflect.InvocationTargetException;
import wslite.json.JSONException;

public interface ConfiguratorService {

  /**
   * Update the value of indicators using {@link
   * com.d3works.apps.sale.db.ConfiguratorCreator#configuratorFormulaList} and the current values in
   * {@link Configurator#attributes}
   *
   * @param configurator
   * @param attributes
   * @param saleOrderId id of parent sale order, can be null.
   * @param indicators @return the new values of indicators
   */
  void updateIndicators(
      Configurator configurator, JsonContext attributes, JsonContext indicators, Long saleOrderId)
      throws D3worksException;

  /**
   * Give the result of a formula, with the script variables defined in the values map.
   *
   * @param groovyFormula
   * @param values
   * @return
   * @throws D3worksException
   */
  Object computeFormula(String groovyFormula, JsonContext values) throws D3worksException;

  /**
   * Generate a product from the configurator
   *
   * @param configurator
   * @param jsonAttributes
   * @param jsonIndicators
   * @param saleOrderId
   */
  void generateProduct(
      Configurator configurator,
      JsonContext jsonAttributes,
      JsonContext jsonIndicators,
      Long saleOrderId)
      throws NoSuchMethodException, InvocationTargetException, IllegalAccessException,
          JSONException, ClassNotFoundException, D3worksException;

  /**
   * Generate a product, then generate a sale order line with the created product, then add this
   * line to the sale order.
   *
   * @param configurator
   * @param saleOrder
   * @param jsonAttributes
   * @param jsonIndicators
   */
  void addLineToSaleOrder(
      Configurator configurator,
      SaleOrder saleOrder,
      JsonContext jsonAttributes,
      JsonContext jsonIndicators)
      throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
          InvocationTargetException, D3worksException;

  /**
   * Check if the calculated value type is the same as the indicator type.
   *
   * @param calculatedValue the return value of a script.
   * @param indicator an indicator.
   * @throws D3worksException if the types don't match.
   */
  void checkType(Object calculatedValue, MetaJsonField indicator) throws D3worksException;

  /**
   * Return true if {@code fromClassName} is a class that can be converted to {@code
   * targetClassName}. <br>
   * Else return false.
   */
  boolean areCompatible(String targetClassName, String fromClassName);

  /**
   * Fix relational fields of a product or a sale order line generated from a configurator. This
   * method may become useless on a future ADK update.
   *
   * @param model
   */
  void fixRelationalFields(Model model) throws D3worksException;
}
